#include "enviroment/ocwindow.h"

UWindowBase::UWindowBase()
{
    m_active = false;
    m_caption = "";
    m_width = 0;
    m_height = 0;
    m_mode = EWindowMode::DESKTOP;
    m_opengl_context = nullptr;
    m_window = nullptr;
    m_position_x = 0;
    m_position_y = 0;
    m_input = new UInput();
}
UWindowBase::UWindowBase(const uString &caption, int32 width, int32 height, EWindowMode mode)
{
    m_active = false;
    m_caption = caption;
    m_width = width;
    m_height = height;
    m_mode = mode;
    m_opengl_context = nullptr;
    m_window = nullptr;
    m_position_x = 0;
    m_position_y = 0;
    m_input = new UInput();
}
UWindowBase::~UWindowBase()
{
    if(m_input){
        delete m_input;
    }
    SDL_GL_DeleteContext(this->m_opengl_context);
    SDL_DestroyWindow(this->m_window);

    LOG_DEBUG("Window Has Been Destroyed.");
}

void UWindowBase::SetWindowVisible(uBoolean new_visible)
{
    if (m_window)
    {

        if (new_visible)
        {
            SDL_ShowWindow(this->m_window);
        }
        else
        {
            SDL_HideWindow(this->m_window);
        }
    }
}
void UWindowBase::SetWindowFullscreen(uBoolean new_fullscreen)
{
    if (m_window)
    {

        int32 flgs = SDL_GetWindowFlags(this->m_window);

        if (new_fullscreen && !IS_OPEN_BIT(flgs, SDL_WINDOW_FULLSCREEN))
        {
            SDL_SetWindowFullscreen(this->m_window, SDL_WINDOW_FULLSCREEN);
            this->m_mode = EWindowMode::FULLSCREEN;
            SDL_GetWindowSize(this->m_window, &this->m_width, &this->m_height);
            __resize_callback();
        }
        else if (!new_fullscreen && IS_OPEN_BIT(flgs, SDL_WINDOW_FULLSCREEN))
        {
            SDL_SetWindowFullscreen(this->m_window, 0);
            this->m_mode = EWindowMode::DESKTOP;
            SDL_GetWindowSize(this->m_window, &this->m_width, &this->m_height);
            __resize_callback();
        }
    }
}
void UWindowBase::SetWindowMaximize(uBoolean new_max)
{
    if (m_window)
    {

        if (new_max)
        {
            SDL_MaximizeWindow(this->m_window);
        }
    }
}
void UWindowBase::SetWindowMinimize(uBoolean new_min)
{
    if (m_window)
    {

        if (new_min)
        {
            SDL_MinimizeWindow(this->m_window);
        }
    }
}

void UWindowBase::SetWindowSize(int32 width, int32 height)
{
    if (m_window)
    {

        this->m_width = width;
        this->m_height = height;
        SDL_SetWindowSize(this->m_window, width, height);
        __resize_callback();
    }
}
void UWindowBase::SetWindowPosition(int32 x, int32 y)
{
    if (m_window)
    {

        this->m_position_x = x;
        this->m_position_y = y;
        SDL_SetWindowPosition(this->m_window, x, y);
    }
}
void UWindowBase::SetWindowCaption(const uString &caption)
{
    if (m_window)
    {

        this->m_caption = caption;
        SDL_SetWindowTitle(this->m_window, caption.c_str());
    }
}

uBoolean UWindowBase::IsWindowVisible() const
{
    if (m_window)
    {

        int32 flgs = SDL_GetWindowFlags(this->m_window);
        return IS_OPEN_BIT(flgs, SDL_WINDOW_SHOWN);
    }
    return false;
}
uBoolean UWindowBase::IsWindowFullscreen() const
{
    if (m_window)
    {

        int32 flgs = SDL_GetWindowFlags(this->m_window);
        return IS_OPEN_BIT(flgs, SDL_WINDOW_FULLSCREEN) || IS_OPEN_BIT(flgs, SDL_WINDOW_FULLSCREEN_DESKTOP);
    }
    return false;
}

int32 UWindowBase::GetWidth() const
{
    return this->m_width;
}
int32 UWindowBase::GetHeight() const
{
    return this->m_height;
}
int32 UWindowBase::GetPositionX() const
{
    return this->m_position_x;
}
int32 UWindowBase::GetPositionY() const
{

    return this->m_position_y;
}
uString UWindowBase::GetCaption() const
{
    return this->m_caption;
}
EWindowMode UWindowBase::GetCurrentDisplayMode() const
{
    return m_mode;
}

uBoolean UWindowBase::IsWindowActive() const
{
    return m_active;
}

UInput* UWindowBase::GetInputer()
{
    return m_input;
}

UEditorWindow::UEditorWindow() : Super()
{
}

UEditorWindow::UEditorWindow(const uString &caption, int32 width, int32 height, EWindowMode mode) : Super(caption, width, height, mode)
{
}

UEditorWindow::~UEditorWindow()
{
    // Cleanup
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplSDL2_Shutdown();
    ImGui::DestroyContext();
    LOG_DEBUG("ImGUI Quit...");
}

void UEditorWindow::ClearBuffer()
{
    glClearColor(0, 0, 0, 1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void UEditorWindow::SwapBuffer()
{
    SDL_GL_SwapWindow(this->m_window);
}

void UEditorWindow::ProcEvent()
{

    SDL_Event ev;
    while (SDL_PollEvent(&ev))
    {
        ImGui_ImplSDL2_ProcessEvent(&ev);
        switch (ev.type)
        {
        case SDL_QUIT:
            delete GInputer;
            this->m_active = false;
            break;
        case SDL_WINDOWEVENT:
            if (ev.window.event == SDL_WINDOWEVENT_RESIZED)
            {
            }
            break;
        case SDL_KEYDOWN:
            if (true)
            {
#ifdef UENGINE_INPUTSYSTEM_AGENT_EVENT
                auto kf = m_input->m_keys_map.find(EKeyCode(ev.key.keysym.sym));
                if (kf == m_input->m_keys_map.end())
                {
                    m_input->m_keys_map.insert(std::make_pair(EKeyCode(ev.key.keysym.sym), true));
                }
                else
                {
                    (*kf).second = true;
                }
                auto keyf = m_input->m_key_events.find(EKeyCode(ev.key.keysym.sym));
                if (keyf != m_input->m_key_events.end())
                {
                    if ((*keyf).second.first == UInput::InputType::KeyDown)
                    {
                        (*keyf).second.second();
                    }
                }

#else
                auto keyf = m_input->m_key_events.find(KeyCode(ev.key.keysym.scancode));
                if (keyf != m_input->m_key_events.end())
                {
                    if ((*keyf).second.first == UInput::InputType::KeyDown)
                    {
                        (*keyf).second.second();
                    }
                }
#endif
            }
            break;
        case SDL_KEYUP:
            if (true)
            {
#ifdef UENGINE_INPUTSYSTEM_AGENT_EVENT
                auto kf = m_input->m_keys_map.find(EKeyCode(ev.key.keysym.sym));
                if (kf != m_input->m_keys_map.end())
                {
                    (*kf).second = false;
                }
                auto keyf = m_input->m_key_events.find(EKeyCode(ev.key.keysym.sym));
                if (keyf != m_input->m_key_events.end())
                {
                    if ((*keyf).second.first == UInput::InputType::KeyRelease)
                    {
                        (*keyf).second.second();
                    }
                }
#else
                auto keyf = m_input->m_key_events.find(KeyCode(ev.key.keysym.scancode));
                if (keyf != m_input->m_key_events.end())
                {
                    if ((*keyf).second.first == UInput::InputType::KeyRelease)
                    {
                        (*keyf).second.second();
                    }
                }

#endif
            }
            break;
        case SDL_MOUSEMOTION:
            m_input->m_mouse_position.X = ev.motion.x;
            m_input->m_mouse_position.Y = ev.motion.y;
            break;
        case SDL_MOUSEBUTTONDOWN:
            if (ev.button.button == SDL_BUTTON_LEFT)
            {
                auto f = m_input->m_mouse_button.find(EMouseButton::Left);
                if (f != m_input->m_mouse_button.end())
                {
                    (*f).second = true;
                }
            }
            else if (ev.button.button == SDL_BUTTON_RIGHT)
            {
                auto f = m_input->m_mouse_button.find(EMouseButton::Right);
                if (f != m_input->m_mouse_button.end())
                {
                    (*f).second = true;
                }
            }
            else if (ev.button.button == SDL_BUTTON_MIDDLE)
            {
                auto f = m_input->m_mouse_button.find(EMouseButton::Middle);
                if (f != m_input->m_mouse_button.end())
                {
                    (*f).second = true;
                }
            }
            break;
        case SDL_MOUSEBUTTONUP:
            if (ev.button.button == SDL_BUTTON_LEFT)
            {
                auto f = m_input->m_mouse_button.find(EMouseButton::Left);
                if (f != m_input->m_mouse_button.end())
                {
                    (*f).second = false;
                }
            }
            else if (ev.button.button == SDL_BUTTON_RIGHT)
            {
                auto f = m_input->m_mouse_button.find(EMouseButton::Right);
                if (f != m_input->m_mouse_button.end())
                {
                    (*f).second = false;
                }
            }
            else if (ev.button.button == SDL_BUTTON_MIDDLE)
            {
                auto f = m_input->m_mouse_button.find(EMouseButton::Middle);
                if (f != m_input->m_mouse_button.end())
                {
                    (*f).second = false;
                }
            }
            break;
        case SDL_MOUSEWHEEL:
            // mouse wheel up
            if (ev.wheel.y > 0)
            {
            }
            // mouse wheel down
            else if (ev.wheel.y < 0)
            {
            }
            // mouse wheel right
            else if (ev.wheel.x > 0)
            {
            }
            // mouse wheel left
            else if (ev.wheel.x < 0)
            {
            }
            break;
        default:
            break;
        }
    }
}

uBoolean UEditorWindow::__create()
{
    // Decide GL+GLSL versions
#if defined(IMGUI_IMPL_OPENGL_ES2)
    // GL ES 2.0 + GLSL 100
    const char *glsl_version = "#version 100";
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#elif defined(__APPLE__)
    // GL 3.2 Core + GLSL 150
    const char *glsl_version = "#version 150";
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
#else
    // GL 3.0 + GLSL 130
    const char *glsl_version = "#version 330";
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
#endif

    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    int32 wmod = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | (int32)m_mode;
    this->m_window = SDL_CreateWindow(m_caption.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, this->m_width, this->m_height, wmod);
    if (!this->m_window)
    {
        LOG_ERROR("Create Window Failure:%s", SDL_GetError());
        // std::cout << "Create Window Failure:" << SDL_GetError() << std::endl;
        return false;
    }
    SDL_GetWindowPosition(this->m_window, &this->m_position_x, &this->m_position_y);
    this->m_opengl_context = SDL_GL_CreateContext(this->m_window);
    if (!this->m_opengl_context)
    {
        LOG_ERROR("Create Window Failure:%s", SDL_GetError());
        // std::cout << "Create Window Failure:" << SDL_GetError() << std::endl;
        SDL_DestroyWindow(this->m_window);
        return false;
    }
    SDL_GL_MakeCurrent(this->m_window, this->m_opengl_context);

    GLenum isOk = glewInit();
    if (isOk != GLEW_OK)
    {
        LOG_ERROR("Create Window Failure:GLEW Init Failure.");
        // std::cout << "Create Window Failure:GLEW Init Failure" << std::endl;
        SDL_GL_DeleteContext(this->m_opengl_context);
        SDL_DestroyWindow(this->m_window);
        return false;
    }

    /////////////////////////////////////
    // Setup Dear ImGui context
    LOG_DEBUG("ImGUI Init...");
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO &io = ImGui::GetIO();
    (void)io;
    // io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls

    // Setup Dear ImGui style
    ImGui::StyleColorsDark();
    // ImGui::StyleColorsLight();

    // Setup Platform/Renderer backends
    ImGui_ImplSDL2_InitForOpenGL(m_window, m_opengl_context);
    ImGui_ImplOpenGL3_Init(glsl_version);
    LOG_DEBUG("ImGUI Init Done.");
    ////////////////////////////////////

    glViewport(0, 0, this->m_width, this->m_height);

    LOG_DEBUG("Create Window With %#X", this->m_window);
    // std::cout << "Create Window:" << this->m_window << std::endl;

    this->m_active = true;
    return true;
}

void UEditorWindow::__resize_callback()
{
    LOG_DEBUG("Window.Viewport Resized.");
    glViewport(0, 0, this->m_width, this->m_height);
}
void UEditorWindow::__test_draw()
{
    // Start the Dear ImGui frame
    ImGui_ImplOpenGL3_NewFrame();
    ImGui_ImplSDL2_NewFrame();
    ImGui::NewFrame();

    ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
    ImGui::Button("Button");
    ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
    ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
    ImGui::End();
    // Rendering
    ImGui::Render();
    ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
    // LOG_INFO("Draw ImGUI Window...");
}

UGameWindow::UGameWindow() : Super()
{
}

UGameWindow::UGameWindow(const uString &caption, int32 width, int32 height, EWindowMode mode) : Super(caption, width, height, mode)
{
}

UGameWindow::~UGameWindow()
{
    // Cleanup
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplSDL2_Shutdown();
    ImGui::DestroyContext();
    LOG_DEBUG("ImGUI Quit...");
}

void UGameWindow::ClearBuffer()
{
    glClearColor(0, 0, 0, 1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void UGameWindow::SwapBuffer()
{
    SDL_GL_SwapWindow(this->m_window);
}

void UGameWindow::ProcEvent()
{

    SDL_Event ev;
    while (SDL_PollEvent(&ev))
    {
        ImGui_ImplSDL2_ProcessEvent(&ev);
        switch (ev.type)
        {
        case SDL_QUIT:
            delete GInputer;
            this->m_active = false;
            break;
        case SDL_WINDOWEVENT:
            if (ev.window.event == SDL_WINDOWEVENT_RESIZED)
            {
            }
            break;
        case SDL_KEYDOWN:
            if (true)
            {
#ifdef UENGINE_INPUTSYSTEM_AGENT_EVENT
                auto kf = m_input->m_keys_map.find(EKeyCode(ev.key.keysym.sym));
                if (kf == m_input->m_keys_map.end())
                {
                    m_input->m_keys_map.insert(std::make_pair(EKeyCode(ev.key.keysym.sym), true));
                }
                else
                {
                    (*kf).second = true;
                }
                auto keyf = m_input->m_key_events.find(EKeyCode(ev.key.keysym.sym));
                if (keyf != m_input->m_key_events.end())
                {
                    if ((*keyf).second.first == UInput::InputType::KeyDown)
                    {
                        (*keyf).second.second();
                    }
                }

#else
                auto keyf = m_input->m_key_events.find(KeyCode(ev.key.keysym.scancode));
                if (keyf != m_input->m_key_events.end())
                {
                    if ((*keyf).second.first == UInput::InputType::KeyDown)
                    {
                        (*keyf).second.second();
                    }
                }
#endif
            }
            break;
        case SDL_KEYUP:
            if (true)
            {
#ifdef UENGINE_INPUTSYSTEM_AGENT_EVENT
                auto kf = m_input->m_keys_map.find(EKeyCode(ev.key.keysym.sym));
                if (kf != m_input->m_keys_map.end())
                {
                    (*kf).second = false;
                }
                auto keyf = m_input->m_key_events.find(EKeyCode(ev.key.keysym.sym));
                if (keyf != m_input->m_key_events.end())
                {
                    if ((*keyf).second.first == UInput::InputType::KeyRelease)
                    {
                        (*keyf).second.second();
                    }
                }
#else
                auto keyf = m_input->m_key_events.find(KeyCode(ev.key.keysym.scancode));
                if (keyf != m_input->m_key_events.end())
                {
                    if ((*keyf).second.first == UInput::InputType::KeyRelease)
                    {
                        (*keyf).second.second();
                    }
                }

#endif
            }
            break;
        case SDL_MOUSEMOTION:
            m_input->m_mouse_position.X = ev.motion.x;
            m_input->m_mouse_position.Y = ev.motion.y;
            break;
        case SDL_MOUSEBUTTONDOWN:
            if (ev.button.button == SDL_BUTTON_LEFT)
            {
                auto f = m_input->m_mouse_button.find(EMouseButton::Left);
                if (f != m_input->m_mouse_button.end())
                {
                    (*f).second = true;
                }
            }
            else if (ev.button.button == SDL_BUTTON_RIGHT)
            {
                auto f = m_input->m_mouse_button.find(EMouseButton::Right);
                if (f != m_input->m_mouse_button.end())
                {
                    (*f).second = true;
                }
            }
            else if (ev.button.button == SDL_BUTTON_MIDDLE)
            {
                auto f = m_input->m_mouse_button.find(EMouseButton::Middle);
                if (f != m_input->m_mouse_button.end())
                {
                    (*f).second = true;
                }
            }
            break;
        case SDL_MOUSEBUTTONUP:
            if (ev.button.button == SDL_BUTTON_LEFT)
            {
                auto f = m_input->m_mouse_button.find(EMouseButton::Left);
                if (f != m_input->m_mouse_button.end())
                {
                    (*f).second = false;
                }
            }
            else if (ev.button.button == SDL_BUTTON_RIGHT)
            {
                auto f = m_input->m_mouse_button.find(EMouseButton::Right);
                if (f != m_input->m_mouse_button.end())
                {
                    (*f).second = false;
                }
            }
            else if (ev.button.button == SDL_BUTTON_MIDDLE)
            {
                auto f = m_input->m_mouse_button.find(EMouseButton::Middle);
                if (f != m_input->m_mouse_button.end())
                {
                    (*f).second = false;
                }
            }
            break;
        case SDL_MOUSEWHEEL:
            // mouse wheel up
            if (ev.wheel.y > 0)
            {
            }
            // mouse wheel down
            else if (ev.wheel.y < 0)
            {
            }
            // mouse wheel right
            else if (ev.wheel.x > 0)
            {
            }
            // mouse wheel left
            else if (ev.wheel.x < 0)
            {
            }
            break;
        default:
            break;
        }
    }
}

uBoolean UGameWindow::__create()
{
    // Decide GL+GLSL versions
#if defined(IMGUI_IMPL_OPENGL_ES2)
    // GL ES 2.0 + GLSL 100
    const char *glsl_version = "#version 100";
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#elif defined(__APPLE__)
    // GL 3.2 Core + GLSL 150
    const char *glsl_version = "#version 150";
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
#else
    // GL 3.0 + GLSL 130
    const char *glsl_version = "#version 330";
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
#endif

    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    int32 wmod = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | (int32)m_mode;
    this->m_window = SDL_CreateWindow(m_caption.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, this->m_width, this->m_height, wmod);
    if (!this->m_window)
    {
        LOG_ERROR("Create Window Failure:%s", SDL_GetError());
        // std::cout << "Create Window Failure:" << SDL_GetError() << std::endl;
        return false;
    }
    SDL_GetWindowPosition(this->m_window, &this->m_position_x, &this->m_position_y);
    this->m_opengl_context = SDL_GL_CreateContext(this->m_window);
    if (!this->m_opengl_context)
    {
        LOG_ERROR("Create Window Failure:%s", SDL_GetError());
        // std::cout << "Create Window Failure:" << SDL_GetError() << std::endl;
        SDL_DestroyWindow(this->m_window);
        return false;
    }
    SDL_GL_MakeCurrent(this->m_window, this->m_opengl_context);

    GLenum isOk = glewInit();
    if (isOk != GLEW_OK)
    {
        LOG_ERROR("Create Window Failure:GLEW Init Failure.");
        // std::cout << "Create Window Failure:GLEW Init Failure" << std::endl;
        SDL_GL_DeleteContext(this->m_opengl_context);
        SDL_DestroyWindow(this->m_window);
        return false;
    }

    /////////////////////////////////////
    // Setup Dear ImGui context
    LOG_DEBUG("ImGUI Init...");
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO &io = ImGui::GetIO();
    (void)io;
    // io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls

    // Setup Dear ImGui style
    ImGui::StyleColorsDark();
    // ImGui::StyleColorsLight();

    // Setup Platform/Renderer backends
    ImGui_ImplSDL2_InitForOpenGL(m_window, m_opengl_context);
    ImGui_ImplOpenGL3_Init(glsl_version);
    LOG_DEBUG("ImGUI Init Done.");
    ////////////////////////////////////

    glViewport(0, 0, this->m_width, this->m_height);

    LOG_DEBUG("Create Window With %#X", this->m_window);
    // std::cout << "Create Window:" << this->m_window << std::endl;

    this->m_active = true;
    return true;
}

void UGameWindow::__resize_callback()
{
    LOG_DEBUG("Window.Viewport Resized.");
    glViewport(0, 0, this->m_width, this->m_height);
}

void UGameWindow::__test_draw()
{
    // Start the Dear ImGui frame
    ImGui_ImplOpenGL3_NewFrame();
    ImGui_ImplSDL2_NewFrame();
    ImGui::NewFrame();

    ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
    ImGui::Button("Button");
    ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
    ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
    ImGui::End();
    // Rendering
    ImGui::Render();
    ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
    // LOG_INFO("Draw ImGUI Window...");
}
